package com.wenbing.miio.mi;

import com.wenbing.miio.core.*;
import com.wenbing.miio.core.exception.DataFormatException;
import com.wenbing.miio.core.exception.NetworkLayerException;
import com.wenbing.miio.util.BytesUtils;
import com.wenbing.miio.util.CipherUtil;

import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

/**
 * 加解密适配层
 * @author wen bing
 * @projectName: miio
 * @package: com.wenbing.miio.core
 * @className: A
 * @date 2024/09/19 14:08
 **/
public class MiCodecLayer extends AbstractShareContextNetworkLayer {

    @Override
    public ByteBuffer unpacking(NetworkLayerContext context, ByteBuffer packingData) throws IOException, NetworkLayerException {
        if (packingData.limit() == 0) {
            LOGGER.debug("unpacking packingData length is 0, nothing to do");
            return packingData;
        }
        // 数据解密
        try {
            byte[] token = MiDeviceUtil.getToken(this);
            byte[] key = CipherUtil.md5( token );
            byte[] iv = CipherUtil.md5( BytesUtils.marginArray(key , token ) );
            int offset = packingData.arrayOffset();
            byte[] decodeData = CipherUtil.deAesCbc(iv , key , packingData.array(), offset + packingData.position(), packingData.limit());
            return ByteBuffer.wrap(decodeData);
        } catch (NoSuchPaddingException | InvalidAlgorithmParameterException | NoSuchAlgorithmException e) {
            throw new NetworkLayerException(e);
        } catch (IllegalBlockSizeException | InvalidKeyException | BadPaddingException e) {
            throw new DataFormatException(e);
        }
    }

    @Override
    public ByteBuffer packing(NetworkLayerContext context, ByteBuffer unpackingData) throws IOException, NetworkLayerException {
        // 加密数据
        try {
            if (unpackingData.limit() == 0) {
                LOGGER.debug("packing unpackingData length is 0, nothing to do");
                return unpackingData;
            }
            byte[] token = MiDeviceUtil.getToken(this);
            byte[] key = CipherUtil.md5( token );
            byte[] iv = CipherUtil.md5( BytesUtils.marginArray(key , token ) );
            int offset = unpackingData.arrayOffset();
            byte[] encodeData = CipherUtil.aesCbc(iv , key , unpackingData.array(), offset + unpackingData.position(), unpackingData.limit());
            return ByteBuffer.wrap(encodeData);
        } catch (NoSuchPaddingException | NoSuchAlgorithmException | InvalidAlgorithmParameterException e) {
            throw new NetworkLayerException(e);
        } catch (IllegalBlockSizeException | InvalidKeyException | BadPaddingException e) {
            throw new DataFormatException(e);
        }
    }
}
